Mysql中的锁机制

您所在的位置:网站首页 mysql 查询锁表 Mysql中的锁机制

Mysql中的锁机制

2023-10-20 17:15| 来源: 网络整理| 查看: 265

MyISAM表锁 MyISAM表锁1、MyISAM表锁1.1、MyISAM存储引擎的锁阻塞实例1.2、如何加表锁1.3、查询表级锁争用情况1.4、并发插入(Concurrent Inserts) 参考:

MyISAM表锁 1、MyISAM表锁

MySQL的表级锁有两种模式:表共享读锁(Table Read Lock)和表独占写锁(Table Write Lock)。

对MyISAM表的读操作,不会阻塞其他用户对同一表的读请求,但会阻塞对同一表的写请求;对 MyISAM表的写操作,则会阻塞其他用户对同一表的读和写操作;MyISAM表的读操作与写操作之间,以及写操作之间是串行的!根据如表20-2所示的 例子可以知道,当一个线程获得对一个表的写锁后,只有持有锁的线程可以对表进行更新操作。其他线程的读、写操作都会等待,直到锁被释放为止。

1.1、MyISAM存储引擎的锁阻塞实例

MyISAM存储引擎的写锁阻塞读例子

当一个线程获得对一个表的写锁后,只有持有锁的线程可以对表进行更新操作。其他线程的读、写操作都会等待,直到锁被释放为止。 在这里插入图片描述 MyISAM存储引擎的读锁阻塞写例子:

一个session使用LOCK TABLE命令给表film_text加了读锁,这个session可以查询锁定表中的记录,但更新或访问其他表都会提示错误;同时,另外一个session可以查询表中的记录,但更新就会出现锁等待。 在这里插入图片描述

1.2、如何加表锁

MyISAM在执行查询语句(SELECT)前,会自动给涉及的所有表加读锁,在执行更新操作 (UPDATE、DELETE、INSERT等)前,会自动给涉及的表加写锁,这个过程并不需要用户干预,因此,用户一般不需要直接用LOCK TABLE命令给MyISAM表显式加锁。在示例中,显式加锁基本上都是为了演示而已,并非必须如此。

给MyISAM表显示加锁,一般是为了在一定程度模拟事务操作,实现对某一时间点多个表的一致性读取。例如, 有一个订单表orders,其中记录有各订单的总金额total,同时还有一个订单明细表order_detail,其中记录有各订单每一产品的金额小计 subtotal,假设我们需要检查这两个表的金额合计是否相符,可能就需要执行如下两条SQL:

Select sum(total) from orders; Select sum(subtotal) from order_detail;

这时,如果不先给两个表加锁,就可能产生错误的结果,因为第一条语句执行过程中,order_detail表可能已经发生了改变。因此,正确的方法应该是:

Lock tables orders read local, order_detail read local; Select sum(total) from orders; Select sum(subtotal) from order_detail; Unlock tables;

要特别说明以下两点内容:

1、上面的例子在LOCK TABLES时加了“local”选项,其作用就是在满足MyISAM表并发插入条件的情况下,允许其他用户在表尾并发插入记录,有关MyISAM表的并发插入问题,在后面还会进一步介绍。2、在用LOCK TABLES给表显式加表锁时,必须同时取得所有涉及到表的锁,并且MySQL不支持锁升级。也就是说,在执行LOCK TABLES后,只能访问显式加锁的这些表,不能访问未加锁的表;同时,如果加的是读锁,那么只能执行查询操作,而不能执行更新操作。其实,在自动加锁的情况下也基本如此,MyISAM总是一次获得SQL语句所需要的全部锁。这也正是MyISAM表不会出现死锁(Deadlock Free)的原因。

当使用LOCK TABLES时,不仅需要一次锁定用到的所有表,而且,同一个表在SQL语句中出现多少次,就要通过与SQL语句中相同的别名锁定多少次,否则也会出错!举例说明如下。

(1)对actor表获得读锁:

mysql> lock table actor read;Query OK, 0 rows affected (0.00 sec)

(2)但是通过别名访问会提示错误:

mysql> select a.first_name,a.last_name,b.first_name,b.last_name from actor a,actor b where a.first_name = b.first_name and a.first_name = 'Lisa' and a.last_name = 'Tom' and a.last_name b.last_name; ERROR 1100 (HY000): Table ‘a’ was not locked with LOCK TABLES

(3)需要对别名分别锁定:

mysql> lock table actor as a read,actor as b read; Query OK, 0 rows affected (0.00 sec)

(4)按照别名的查询可以正确执行:

mysql> select a.first_name,a.last_name,b.first_name,b.last_name from actor a,actor b where a.first_name = b.first_name and a.first_name = 'Lisa' and a.last_name = 'Tom' and a.last_name b.last_name; +————+———–+————+———–+ | first_name | last_name | first_name | last_name | +————+———–+————+———–+ | Lisa | Tom | LISA | MONROE | +————+———–+————+———–+ 1 row in set (0.00 sec) 1.3、查询表级锁争用情况

可以通过检查table_locks_waited和table_locks_immediate状态变量来分析系统上的表锁定争夺:

mysql> show status like 'table%'; Variable_name | Value Table_locks_immediate | 2979 Table_locks_waited | 0 2 rows in set (0.00 sec))

如果Table_locks_waited的值比较高,则说明存在着较严重的表级锁争用情况。

1.4、并发插入(Concurrent Inserts)

上文提到过MyISAM表的读和写是串行的,但这是就总体而言的。在一定条件下,MyISAM表也支持查询和插入操作的并发进行。 MyISAM存储引擎有一个系统变量concurrent_insert,专门用以控制其并发插入的行为,其值分别可以为0、1或2。

当concurrent_insert设置为0时,不允许并发插入。当concurrent_insert设置为1时,如果MyISAM表中没有空洞(即表的中间没有被删除的行),MyISAM允许在一个进程读表的同时,另一个进程从表尾插入记录。这也是MySQL的默认设置。当concurrent_insert设置为2时,无论MyISAM表中有没有空洞,都允许在表尾并发插入记录。

在下面的例子中,session_1获得了一个表的READ LOCAL锁,该线程可以对表进行查询操作,但不能对表进行更新操作;其他的线程(session_2),虽然不能对表进行删除和更新操作,但却可以对该表进行并发插入操作,这里假设该表中间不存在空洞。

MyISAM存储引擎的读写(INSERT)并发例子: 在这里插入图片描述 可以利用MyISAM存储引擎的并发插入特性,来解决应 用中对同一表查询和插入的锁争用。例如,将concurrent_insert系统变量设为2,总是允许并发插入;同时,通过定期在系统空闲时段执行 OPTIMIZE TABLE语句来整理空间碎片,收回因删除记录而产生的中间空洞。

参考:

1、https://www.cnblogs.com/leedaily/p/8378779.html



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3